package com.share.file.service.Impl;

import java.io.InputStream;

import com.share.file.service.ISysFileService;
import io.minio.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.nacos.common.utils.IoUtils;
import com.share.file.config.MinioConfig;
import com.share.file.utils.FileUploadUtils;

/**
 * Minio 文件存储
 *
 * @author share
 */
@Service("minioSysFileService")
@RequiredArgsConstructor
public class MinioSysFileServiceImpl implements ISysFileService {
    private final MinioConfig minioConfig;
    private final MinioClient client;
    private volatile boolean bucketPolicySet = false;

    /**
     * Minio文件上传接口
     *
     * @param file 上传的文件
     * @return 访问地址
     */
    @Override
    public String uploadFile(MultipartFile file) throws Exception {
        // 确保存储桶存在并设置为公开
        ensureBucketPublic();

        String fileName = FileUploadUtils.extractFilename(file);
        InputStream inputStream = file.getInputStream();
        PutObjectArgs args = PutObjectArgs.builder()
                .bucket(minioConfig.getBucketName())
                .object(fileName)
                .stream(inputStream, file.getSize(), -1)
                .contentType(file.getContentType())
                .build();
        client.putObject(args);
        IoUtils.closeQuietly(inputStream);

        // 生成预签名URL(7天)
        String url = getFileUrl(fileName);
        System.err.println("url是：" + url);

        return url;
    }

    /**
     * 确保存储桶存在并设置为公开访问
     */
    private void ensureBucketPublic() throws Exception {
        if (bucketPolicySet) {
            return;
        }

        String bucketName = minioConfig.getBucketName();

        // 检查存储桶是否存在
        boolean found = client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        if (!found) {
            // 创建存储桶
            client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }

        // 设置存储桶为公开读取
        String policyJson = createPublicReadPolicy(bucketName);
        client.setBucketPolicy(
                SetBucketPolicyArgs.builder()
                        .bucket(bucketName)
                        .config(policyJson)
                        .build()
        );

        bucketPolicySet = true;
        System.out.println("存储桶 " + bucketName + " 已设置为公开访问");
    }

    /**
     * 创建公开读取策略
     */
    private String createPublicReadPolicy(String bucketName) {
        return String.format(
                """
                        {
                          "Version": "2012-10-17",
                          "Statement": [
                            {
                              "Effect": "Allow",
                              "Principal": "*",
                              "Action": ["s3:GetObject"],
                              "Resource": ["arn:aws:s3:::%s/*"]
                            }
                          ]
                        }""", bucketName);
    }

    /**
     * 获取文件完整访问URL
     */
    public String getFileUrl(String fileName) {
        return minioConfig.getPublicUrl() + "/" + fileName;
    }
}
